/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef ARKUI_NATIVE_ANIMATE_IMPL_H
#define ARKUI_NATIVE_ANIMATE_IMPL_H

#include <cstdint>
#include <vector>

#include "native_animate.h"
#include "native_type.h"

#include "frameworks/core/interfaces/arkoala/arkoala_api.h"

#ifdef __cplusplus
extern "C" {
#endif

struct Keels_ArkUI_AnimateOption {
    uint32_t duration;
    float tempo;
    Keels_ArkUI_AnimationCurve curve;
    int32_t delay;
    int32_t iterations;
    Keels_ArkUI_AnimationPlayMode playMode;
    Keels_ArkUI_ExpectedFrameRateRange* expectedFrameRateRange;
    Keels_ArkUI_CurveHandle iCurve;
};

typedef enum {
    ARKUI_CURVE_TYPE_BASE = 0,
    ARKUI_CURVE_TYPE_STEPS,
    ARKUI_CURVE_TYPE_CUBIC_BEZIER,
    ARKUI_CURVE_TYPE_SPRING,
    ARKUI_CURVE_TYPE_SPRING_MOTION,
    ARKUI_CURVE_TYPE_RESPONSIVE_SPRING_MOTION,
    ARKUI_CURVE_TYPE_INTERPOLATING_SPRING,
    ARKUI_CURVE_TYPE_CUSTOM,
} ArkUI_CurveType;

struct Keels_ArkUI_Curve {
    ArkUI_CurveType type;
    ArkUICurveHandle curve;
    Keels_ArkUI_AnimationCurve baseCurveType;
};

struct ArkUI_KeyframeState {
    int32_t duration;
    Keels_ArkUI_CurveHandle curve;
    void (*event)(void* userData);
    void* userData;
};

struct Keels_ArkUI_KeyframeAnimateOption {
    int32_t delay;
    int32_t iterations;
    void (*onFinish)(void* userData);
    void* userData;
    std::vector<ArkUI_KeyframeState> keyframes;
};

struct ArkUI_Keyframe {
    float keyTime;
    float keyValue;
    Keels_ArkUI_CurveHandle curve;
};
struct Keels_ArkUI_AnimatorOption {
    int32_t duration;
    int32_t delay;
    int32_t iterations;
    Keels_ArkUI_AnimationFillMode fill;
    Keels_ArkUI_AnimationDirection direction;
    float begin;
    float end;
    Keels_ArkUI_CurveHandle easing;
    Keels_ArkUI_ExpectedFrameRateRange* expectedFrameRateRange;
    std::vector<ArkUI_Keyframe> keyframes;
    void (*onFrame)(Keels_ArkUI_AnimatorOnFrameEvent* event);
    void* frameUserData;
    void (*onFinish)(Keels_ArkUI_AnimatorEvent* event);
    void* finishUserData;
    void (*onCancel)(Keels_ArkUI_AnimatorEvent* event);
    void* cancelUserData;
    void (*onRepeat)(Keels_ArkUI_AnimatorEvent* event);
    void* repeatUserData;
};

struct Keels_ArkUI_Animator {
    ArkUIAnimatorHandle animator;
    Keels_ArkUI_AnimatorOption* option;
    ArkUIAnimatorOption* animatorOption;
};
#ifdef __cplusplus
};
#endif

namespace Keels::Ace::AnimateModel {

Keels_ArkUI_CurveHandle InitCurve(Keels_ArkUI_AnimationCurve animationCurve);
Keels_ArkUI_CurveHandle StepsCurve(int32_t count, bool end);
Keels_ArkUI_CurveHandle CubicBezierCurve(float x1, float y1, float x2, float y2);
Keels_ArkUI_CurveHandle SpringCurve(float velocity, float mass, float stiffness, float damping);
Keels_ArkUI_CurveHandle SpringMotion(float response, float dampingFraction, float overlapDuration);
Keels_ArkUI_CurveHandle ResponsiveSpringMotion(float response, float dampingFraction, float overlapDuration);
Keels_ArkUI_CurveHandle InterpolatingSpring(float velocity, float mass, float stiffness, float damping);
Keels_ArkUI_CurveHandle CustomCurve(void* userData, float (*interpolate)(float fraction, void* userdata));
void DisposeCurve(Keels_ArkUI_CurveHandle curveHandle);

int32_t AnimateTo(Keels_ArkUI_ContextHandle context, Keels_ArkUI_AnimateOption* option, Keels_ArkUI_ContextCallback* update,
    Keels_ArkUI_AnimateCompleteCallback* complete);

int32_t KeyframeAnimateTo(Keels_ArkUI_ContextHandle context, Keels_ArkUI_KeyframeAnimateOption* option);

Keels_ArkUI_AnimatorHandle CreateAnimator(Keels_ArkUI_ContextHandle context, Keels_ArkUI_AnimatorOption* option);
void DisposeAnimator(Keels_ArkUI_AnimatorHandle animatorHandle);


int32_t AnimatorReset(Keels_ArkUI_AnimatorHandle animatorHandle, Keels_ArkUI_AnimatorOption* option);
int32_t AnimatorPlay(Keels_ArkUI_AnimatorHandle animatorHandle);
int32_t AnimatorFinish(Keels_ArkUI_AnimatorHandle animatorHandle);
int32_t AnimatorPause(Keels_ArkUI_AnimatorHandle animatorHandle);
int32_t AnimatorCancel(Keels_ArkUI_AnimatorHandle animatorHandle);
int32_t AnimatorReverse(Keels_ArkUI_AnimatorHandle animatorHandle);
}; // namespace Keels::Ace::AnimateModel

#endif